import jsrsasign from 'jsrsasign'
import { OriginRoute } from '@/store/types'
export function isExternal(path: string) {
  return /^(https?:|mailto:|tel:)/.test(path)
}

export function uuid() {
  const s: Array<any> = []
  const hexDigits = '0123456789abcdef'
  for (let i = 0; i < 36; i++) {
    s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
  }
  s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
  s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
  s[8] = s[13] = s[18] = s[23] = '-'
  const uuid = s.join('')
  return uuid
}

export function randomString(length: number) {
  const str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  let result = ''
  for (let i = length; i > 0; --i) {
    result += str[Math.floor(Math.random() * str.length)]
  }
  return result
}

/**
 * 中划线字符驼峰
 * @param {*} str 要转换的字符串
 * @returns 返回值
 */
export function toHump(str: string): string {
  if (!str) return str
  return str
    .replace(/\-(\w)/g, function (all, letter) {
      return letter.toUpperCase()
    })
    .replace(/(\s|^)[a-z]/g, function (char) {
      return char.toUpperCase()
    })
}

/**
 * 时间格式化
 * @param time 
 * @param pattern 
 * @returns 
 */
export function parseTime(time: any, pattern?: any) {
  if (arguments.length === 0 || !time) {
    return null;
  }
  const format = pattern || "{y}-{m}-{d} {h}:{i}:{s}";
  let date;
  if (typeof time === "object") {
    date = time;
  } else {
    if (typeof time === "string" && /^[0-9]+$/.test(time)) {
      time = parseInt(time);
    } else if (typeof time === "string") {
      time = time
        .replace(new RegExp(/-/gm), "/")
        .replace("T", " ")
        .replace(new RegExp(/\.[\d]{3}/gm), "");
    }
    if (typeof time === "number" && time.toString().length === 10) {
      time = time * 1000;
    }
    date = new Date(time);
  }
  const formatObj = {
    y: date.getFullYear(),
    m: date.getMonth() + 1,
    d: date.getDate(),
    h: date.getHours(),
    i: date.getMinutes(),
    s: date.getSeconds(),
    a: date.getDay(),
  };
  type formatObjPropertyType = keyof typeof formatObj;
  const time_str = format.replace(
    /{(y|m|d|h|i|s|a)+}/g,
    (result: any, key: formatObjPropertyType) => {
      let value = formatObj[key];
      // Note: getDay() returns 0 on Sunday
      if (key === "a") {
        return ["日", "一", "二", "三", "四", "五", "六"][value];
      }
      if (result.length > 0 && value < 10) {
        value = "0" + value;
      }
      return value || 0;
    },
  );
  return time_str;
}


export function sortColumns(originColumns: any[], newColumns: any[]) {
  if (!originColumns || !newColumns) {
    return
  }
  if (newColumns.length === 0) {
    originColumns.length = 0
  } else {
    const selectionItem = originColumns.find((it) => it.type === 'selection')
    originColumns.length = 0
    if (selectionItem) {
      originColumns.push(selectionItem)
    }
    originColumns.push(...newColumns)
  }
}

export function getNowDate() {
  const date = new Date()
  const sign2 = ':'
  const year = date.getFullYear() // 年
  let month: string | number = date.getMonth() + 1 // 月
  let day: string | number = date.getDate() // 日
  let hour: string | number = date.getHours() // 时
  let minutes: string | number = date.getMinutes() // 分
  let seconds: string | number = date.getSeconds() //秒
  const weekArr = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天']
  const week = weekArr[date.getDay()]
  // 给一位数的数据前面加 “0”
  if (month >= 1 && month <= 9) {
    month = '0' + month
  }
  if (day >= 0 && day <= 9) {
    day = '0' + day
  }
  if (hour >= 0 && hour <= 9) {
    hour = '0' + hour
  }
  if (minutes >= 0 && minutes <= 9) {
    minutes = '0' + minutes
  }
  if (seconds >= 0 && seconds <= 9) {
    seconds = '0' + seconds
  }
  return [year + '-' + month + '-' + day, hour + sign2 + minutes + sign2 + seconds, week]
}

export const delay = async (maxMs = 3000) => {
  return new Promise<void>((resolve) => {
    setTimeout(() => {
      resolve()
    }, Math.random() * maxMs)
  })
}

// 使用rsa进行加密
export const rsaEncrypt = (newStr: string, secretkey: string) => {
  //创建一个对象
  let rsa = new jsrsasign.RSAKey();
  //使用公钥加密
  let publicKey = "-----BEGIN PUBLIC KEY-----\n" + secretkey + "\n-----END PUBLIC KEY-----";
  rsa = jsrsasign.KEYUTIL.getKey(publicKey)
  var enc = jsrsasign.KJUR.crypto.Cipher.encrypt(newStr,rsa);
  //转换成Base64格式
  let base64Sign = jsrsasign.hextob64(enc);
  return base64Sign
}

export type DataMapping = Partial<Record<keyof OriginRoute, string>>;

export type InputData<T extends DataMapping> = {
  [K in keyof T as T[K] extends string ? T[K] : never]?: any;
};
// 将后端菜单数据转化为我们需要的路由数据
export function transformToOriginRoutes<T extends DataMapping> (dataMapping: T, inputData: InputData<T>[]): OriginRoute[] {
  return inputData.map(data => {
    const originRoute: Partial<OriginRoute> = {};
    for (const key in dataMapping) {
      const mappedKey = dataMapping[key];
      if (mappedKey) {
        // 如果存在子元素
        if (key === 'children') {
          if (data[key as keyof InputData<T>] && Array.isArray(data[key as keyof InputData<T>])) {
            originRoute.children = transformToOriginRoutes(dataMapping, data[key as keyof InputData<T>] as any);
          } else {
            originRoute[key as keyof OriginRoute] = undefined;
          }
        } else {
          const value = data[mappedKey as keyof InputData<T>];
          if (value !== undefined && value !== null) {
            originRoute[key as keyof OriginRoute] = value as any;
          } else {
            originRoute[key as keyof OriginRoute] = undefined; // 或者其他默认值
          }
        }
      }
    }
    return originRoute as OriginRoute;
  });
}

// 判断对象是否为空
export function isEmptyObject(obj: any): boolean {
  for (const key in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, key)) {
      return false;
    }
  }
  return true;
}

/**
 * 比较两个对象是否相等
 * @param {*} obj1
 * @param {*} obj2
 * @returns
 */
export function isDeepEqual(obj1: any, obj2: any) {
  // 如果两个对象引用相同，直接返回 true
  if (obj1 === obj2) {
    return true;
  }

  // 如果其中一个对象为 null 或者不是对象，返回 false
  if (
    obj1 == null ||
    obj2 == null ||
    typeof obj1 !== "object" ||
    typeof obj2 !== "object"
  ) {
    return false;
  }

  // 获取对象的键
  const keys1 = Object.keys(obj1);
  const keys2 = Object.keys(obj2);

  // 如果键的数量不同，返回 false
  if (keys1.length !== keys2.length) {
    return false;
  }

  // 检查每个键的值是否相等
  for (const key of keys1) {
    if (!keys2.includes(key) || !isDeepEqual(obj1[key], obj2[key])) {
      return false;
    }
  }

  return true;
}

/**
 * 根据表单信息构建表单校验数据
 * @param formInfo 
 * @returns 
 */
export function buildFormRules(formInfo: any) {
  const formRules = {} as any
  for (let i in formInfo) {
    const item = formInfo[i]
    if (item.rules) {
      formRules[item.field] = item.rules
    }
    if (item.validator) {
      const rules = formRules[item.field] || []
      // 构建验证规则
      const validator = (value: any, callback: any) => {
        if (item.validator(value)) { // 校验成功
          if (item.feedback) {
            item.validateStatus = 'success'
            item.help = ''
          }
          callback()
        } else { // 校验失败
          if (item.feedback) {
            item.validateStatus = 'error'
            item.help = item.validateMessage
          }
          callback(item.validateMessage)
        }
      }
      // 放在第一个，就先执行我们这个验证，否则可能不会先执行这个验证
      let ret = [{ validator }, ...rules]
      formRules[item.field] = ret
    }
  }
  return formRules
}

/**
 * 构造树型结构数据
 * @param {*} data 数据源
 * @param {*} id id字段 默认 'id'
 * @param {*} parentId 父节点字段 默认 'parentId'
 * @param {*} children 孩子节点字段 默认 'children'
 */
export function handleTree(data: any, id: any = 'id', parentId: any = 'parentId', children: any = 'children') {
  let config = {
    id: id || 'id',
    parentId: parentId || 'parentId',
    childrenList: children || 'children'
  };

  var childrenListMap: any = {};
  var nodeIds: any = {};
  var tree: any = [];

  for (let d of data) {
    let parentId = d[config.parentId];
    if (childrenListMap[parentId] == null) {
      childrenListMap[parentId] = [];
    }
    nodeIds[d[config.id]] = d;
    childrenListMap[parentId].push(d);
  }

  for (let d of data) {
    let parentId = d[config.parentId];
    if (nodeIds[parentId] == null) {
      tree.push(d);
    }
  }

  for (let t of tree) {
    adaptToChildrenList(t);
  }

  function adaptToChildrenList(o: any) {
    if (childrenListMap[o[config.id]] !== null) {
      o[config.childrenList] = childrenListMap[o[config.id]];
    }
    if (o[config.childrenList]) {
      for (let c of o[config.childrenList]) {
        adaptToChildrenList(c);
      }
    }
  }
  return tree;
}

// 是否http链接
export function isHttpPath(path: any) {
  if (!path) {
    return false
  }
  return path.startsWith('http://') || path.startsWith('https://');
}

/**
 * url上拼接查询条件
 * @param url 
 * @param queryParams 
 * @returns 
 */
export function appendQueryParams(url: string, queryParams: Record<string, string>): string {
  const urlObj = new URL(url);
  const searchParams = new URLSearchParams(urlObj.search);

  for (const [key, value] of Object.entries(queryParams)) {
    searchParams.append(key, value);
  }

  urlObj.search = searchParams.toString();
  return urlObj.toString();
}